package com.sky.module.system.sysuser.controller;

import com.sky.config.redis.RedisService;
import com.sky.module.system.permission.domain.entity.Permission;
import com.sky.module.system.user.domain.entity.User;
import com.sky.module.system.user.domain.entity.UserInfo;
import com.sky.module.system.vo.RouterVo;
import com.sky.module.system.vo.TokenVo;
import com.sky.module.system.utils.JwtUtils;
import com.sky.module.system.utils.MenuTree;
import com.sky.utils.Result;
import io.jsonwebtoken.Jwts;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author
 * @date 2023/2/20 16:48
 **/
@RestController
@RequestMapping("/api/sysUser")
public class SysUserController {


    @Resource
    private JwtUtils jwtUtils;

    @Resource
    private RedisService redisService;

    /***
     * @description 刷新token 方法
     *
     * @param request
     * @return com.zsg.utils.Result
     * @date 2023/2/20 16:49
     *
     */
    @PostMapping("/refreshToken")
    public Result refreshToken(HttpServletRequest request) {
        String token = request.getHeader("token");
        String requestURI = request.getRequestURI();
        if (ObjectUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetails userDetails = ((UserDetails) authentication.getPrincipal());

        // 生成token 信息
        String newToken = "";
        if (jwtUtils.validateToken(token, userDetails)) {
//            生成新的token
            newToken = jwtUtils.refreshToken(token);
        }
//         获取本次token的过期时间
        long expireTime = Jwts.parser() //获取DefaultJwtParser对象
                .setSigningKey(jwtUtils.getSecret()) //设置签名的密钥
                .parseClaimsJws(token.replace("jwt_", ""))
                .getBody().getExpiration().getTime();//获取token过期时间
//        long expireTime = Jwts.parser().setSigningKey(jwtUtils.getSecret())
//                .parseClaimsJwt(newToken.replace("jwt_", ""))
//                .getBody().getExpiration().getTime();

        String oldTokenKey = "token_" + token;
        redisService.del(oldTokenKey);
        //        验证提交过来的token信息
        String newTokenKey = "token_" + newToken;
        redisService.set(newTokenKey, newToken, jwtUtils.getExpiration() / 1000);
//        创建tokenvo 对象
        TokenVo tokenVo = new TokenVo();
        tokenVo.setToken(newToken);
        tokenVo.setExpireTime(expireTime);
        return Result.ok(tokenVo).message("token刷新");
    }


    /***
     * @description 获取用户信息
     *
     * @return com.zsg.utils.Result
     * @date 2023/2/20 17:38
     *
     */
    @GetMapping("/getInfo")
    public Result getInfo() {
//         从springscerity 上下文中获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//         authentication  为空
        if (authentication == null) {
            return Result.error().message("查询用户信息失败");
        }
        // 获取用户信息
        User user = (User) authentication.getPrincipal();
//        获取用户角色拥有的权限信息
        final Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
        List<Permission> permissionList = user.getPermissionList();
        List<String> collect = permissionList.stream()
                .filter(Objects::nonNull)
                .map(Permission::getCode).collect(Collectors.toList());
        //        创建用户信息
        Object[] roles = collect.toArray(new Object[collect.size()]);
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setName(user.getNickName());
        userInfo.setIntroduction(null);
        userInfo.setRoles(roles);
        userInfo.setAvatar(user.getAvatar());
        return Result.ok(userInfo).message("用户信息查询成功");
        //         查询
    }

    @GetMapping("getMenuList")
    public Result getMenuList() {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//         获取用户信息
        User user = (User) authentication.getPrincipal();

        // 获取该用户的权限信息
        final List<Permission> permissionList = user.getPermissionList();
//          筛选当前用户拥有的目录和菜单和数据
        final List<Permission> collect = permissionList.stream().filter(item -> item != null && item.getType() != 2)
                .collect(Collectors.toList());
//        生成菜单数据
        List<RouterVo> routeVoList = MenuTree.makeRouter(collect, 0L);
        return Result.ok(routeVoList);
    }

    /***
     * @description 退出登录
     *
     * @return com.zsg.utils.Result
     * @date 2023/2/20 23:35
     *
     */
    @PostMapping("/logout")
    public Result logout(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getParameter("token");
        if (ObjectUtils.isEmpty(token)) {
            token = request.getHeader("token");
            if (ObjectUtils.isEmpty(token)) {
                return Result.error().message("没有携带token");
            }
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
//            清除用户信息
            final SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
            securityContextLogoutHandler.logout(request, response, authentication);
            redisService.del("token_" + token);
            return Result.ok().message("退出成功");
        }


        return Result.error().message("退出失败，用户信息不能为空");
    }

}
